/*
 * =====================================================================================
 *
 *       Filename:  main.cpp
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  11/05/13 05:07:41
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Heaven (), zhanwenhan@163.com
 *        Company:  NDSL
 *
 * =====================================================================================
 */

#include "ClientAgent.h"
// #include "TestTimer.h"

#include "common/Timer/TimerAgent.h"
#include "common/comm/Epoll.h"
#include "common/comm/TCPListenAgent.h"
#include "common/comm/AgentManager.h"
#include "common/comm/TaskManager.h"
#include "common/sys/ThreadPool.h"
#include "common/log/log.h"
#include "common/util/util.h"

#include <stdlib.h>
#include <signal.h>

using util::conv::conv;

TCPListenAgent<ClientAgent> *g_pListenCA = NULL;
ThreadPool *g_pThreadPool = NULL;
ThreadPoolDispatcher *g_pDispatcher = NULL;
SocketAddress servaddr;

const int EPOLLSIZE = 1024;

void doExit(int signo)
{
    if (signo == SIGINT)
    {
        INFO_LOG("server sigint catch!");

        Epoll::getInstance()->finish();
    }
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        cout << "Usage: " << argv[0] << " Port" << endl;
        return FAILED;
    }

    if (Epoll::getInstance()->initialize(EPOLLSIZE) == FAILED)
    {
        ERROR_LOG("\nIn main: init epoll error!\n");
        return FAILED;
    }

    g_pThreadPool = new ThreadPool();
    g_pThreadPool->start();

    //must init epoll and thread pool before
    g_pDispatcher = (AgentManager::getInstance())->createAgent<ThreadPoolDispatcher>();
    g_pDispatcher->init(g_pThreadPool->getWHandle(),
                        tr1::bind(&ThreadPool::postRequest,
                                  g_pThreadPool,
                                  tr1::placeholders::_1));

    servaddr.setPort(conv<unsigned short, char *>(argv[1]));
    g_pListenCA = (AgentManager::getInstance())->createAgent<TCPListenAgent<ClientAgent> >(servaddr);
    g_pListenCA->init();

    TimerAgent *pTimer = (AgentManager::getInstance())->createAgent<TimerAgent>();
    struct timespec starttime, intervaltime;
    starttime.tv_sec = 0;
    starttime.tv_nsec = 1;
    intervaltime.tv_sec = 1;
    intervaltime.tv_nsec = 0;
    pTimer->init(starttime, intervaltime);

    if (signal(SIGINT, doExit) == SIG_ERR)
    {
        ERROR_LOG("\nIn main: set SIGINT(catch \"ctrl+c\") signal error!\n");
        return FAILED;
    }
    Epoll::getInstance()->run();

    AgentManager::destroyInstance();
    TaskManager::destroyInstance();

    g_pThreadPool->stop();
    if (g_pThreadPool != NULL)
    {
        delete g_pThreadPool;
        g_pThreadPool = NULL;
    }

    Epoll::destroyInstance();

    LoggerFactory::getInstance()->clear();
    LoggerFactory::destroyInstance();

    return 0;
}
